package com.lyy.king.auth.service.impl;

import com.lyy.king.auth.config.JwtProperties;
import com.lyy.king.auth.domain.User;
import com.lyy.king.auth.model.LoginInfo;
import com.lyy.king.auth.modal.UserDTO;
import com.lyy.king.auth.model.request.LoginRequest;
import com.lyy.king.auth.model.response.LoginResponse;
import com.lyy.king.auth.service.AuthService;
import com.lyy.king.auth.service.UserService;
import com.lyy.king.common.core.constant.TokenConstants;
import com.lyy.king.common.core.domain.Payload;
import com.lyy.king.common.utils.exception.BizException;
import com.lyy.king.common.utils.exception.CheckParamException;
import com.lyy.king.common.redis.service.RedisService;
import com.lyy.king.tools.request.CheckCaptchaRequest;
import com.lyy.king.common.utils.utils.*;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: springcloud-learning
 * @BelongsPackage: com.cdx.auth.service.impl
 * @Author: cdx
 * @CreateTime: 2022-06-05  15:39
 * @Description:
 * @Version: 1.0
 */
@Service
public class AuthServiceImpl implements AuthService {
    @Autowired
    UserService userService;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private RedisService redisService;

    @Override
    public LoginResponse login(LoginRequest request) {
        // 检查参数是否正确
        CheckParamException.check(!StringUtils.isAnyBlank(request.getUsername(), request.getPassword()), "用户名和密码不能空");
        CheckParamException.check(!StringUtils.isAnyBlank(request.getUuid(), request.getCode()), "验证码不能为空");
        // 检查验证码是否正确
        CheckCaptchaRequest checkCaptchaRequest = new CheckCaptchaRequest();
        checkCaptchaRequest.setCode(request.getCode());
        checkCaptchaRequest.setUuid(request.getUuid());
        //Result<Boolean> checkCaptchaResult = captchaApi.checkCaptcha(checkCaptchaRequest);
        //BizException.check(checkCaptchaResult != null && checkCaptchaResult.getData(), "验证码输入错误");

        // 根据用户名查询用户信息
        User user = userService.selectByUsername(request.getUsername());
        BizException.check(user != null &&
                request.getPassword().equals(user.getPassword()), "用户名/密码错误");
        // 获取 token信息载体信息
        LoginInfo loginInfo = BeanFactoryUtils.copyProperties(user, LoginInfo.class);
        // 生成 token
        String token = JwtUtils.generateToken(loginInfo, jwtProperties.getPrivateKey(),
                DateUtils.addMinutes(new Date(), jwtProperties.getExpire()));
        // 返回token
        LoginResponse response = new LoginResponse();
        response.setToken(token);
        return response;

    }

    @Override
    public UserDTO getTokenLoginInfo() {
        // 获取token
        String token = ServletUtils.getToken();
        // 解析 token
        return parseToken(token);
    }

    @Override
    public Boolean checkToken(String token) {
        // 检查 token
        try {
            // token是否在失效名单中
            if (redisService.hasKey(TokenConstants.getExpireTokenCacheKey(token))) {
                return false;
            }
            // 解析 token
            parseToken(token);
            return true;
        } catch (ExpiredJwtException e) {
            // token过期，返回 false
            return false;
        } catch (Exception e) {
            // 其他错误，返回 false
            return false;
        }
    }

    @Override
    public boolean logout() {
        // 获取token
        String token = ServletUtils.getToken();
        // redis缓存失效的token
        redisService.setCacheObject(TokenConstants.getExpireTokenCacheKey(token), token,
                jwtProperties.getExpire().longValue(), TimeUnit.MINUTES);
        return true;
    }


    /**
     * 解析 token
     *
     * @param token
     * @return
     */
    private UserDTO parseToken(String token) {
        // 解析token
        Payload<LoginInfo> infoFromToken = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey(), LoginInfo.class);
        // 获取登录信息
        LoginInfo loginInfo = infoFromToken.getLoginInfo();
        // 查询用户信息
        User user = userService.selectById(loginInfo.getId());
        return BeanFactoryUtils.copyProperties(user, UserDTO.class);
    }

}
